import cv2
import numpy as np


def sift_kp(image):
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    sift = cv2.xfeatures2d_SIFT.create()
    kp, des = sift.detectAndCompute(image, None)
    kp_image = cv2.drawKeypoints(gray_image, kp, None)
    return kp_image, kp, des

def get_good_match(des1, des2):
    bf = cv2.BFMatcher()
    matches = bf.knnMatch(des1, des2, k=2)
    good_match = []
    for m, n in matches:
        if m.distance < 0.7 * n.distance:
            good_match.append(m)
    return good_match



image1 = cv2.imread("test.png")
image2 = cv2.imread("test2.png")

_, kps1, des1 = sift_kp(image1)
_, kps2, des2 = sift_kp(image2)

good_match = get_good_match(des1, des2)
if len(good_match) > 4:
    pts1 = np.float32([kps1[m.queryIdx].pt for m in good_match]).reshape(-1, 1, 2)
    pts2 = np.float32([kps2[m.trainIdx].pt for m in good_match]).reshape(-1, 1, 2)
    ransac_reporj_threshold = 4
    H, status = cv2.findHomography(pts1, pts2, cv2.RANSAC, ransac_reporj_threshold)
    image_out = cv2.warpPerspective(image2, H, (image1.shape[1], image1.shape[0]), flags=cv2.INTER_LINEAR+cv2.WARP_INVERSE_MAP)
cv2.imwrite("test3.png", image_out)
print(H)